/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ro.unibuc.nautilus.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.springframework.beans.factory.annotation.Required;

import ro.unibuc.nautilus.dao.GenericDAO;
import ro.unibuc.nautilus.domain.Cargo;
import ro.unibuc.nautilus.domain.CruiseShip;
import ro.unibuc.nautilus.domain.Employee;
import ro.unibuc.nautilus.domain.Harbour;
import ro.unibuc.nautilus.domain.Route;
import ro.unibuc.nautilus.domain.Ship;
import ro.unibuc.nautilus.domain.Tanker;
import ro.unibuc.nautilus.domain.User;
import ro.unibuc.nautilus.domain.UserRole;

/**
 * 
 * @author Root
 */
public class UsersServiceImpl implements UsersService {

	private GenericDAO<User, Long> usersDAO;
	private GenericDAO<UserRole, Long> usersRolesDAO;
	
	// TODO: se va sterge dupa ce se stabilizeaza DB
	// sunt necesare pentru initializari - vezi init()'
	private GenericDAO<Harbour, Long> harboursDAO;
	private GenericDAO<Ship, Long> shipsDAO;
	private GenericDAO<Route, Long> routesDAO;
	private GenericDAO<Employee, Long> employeesDAO;

	public UsersServiceImpl() {
	}

	public User findUser(Long id) {
		return usersDAO.find(id);
	}

	public List<User> findAll() {
		return usersDAO.findAll();
	}

	public void create(User user) {
		usersDAO.create(user);
	}

	public void createRole(UserRole userRole) {
		usersRolesDAO.create(userRole);
	}

	/**
	 * Create initial random details. <br/>
	 * Invoked by Spring using the init-method bean argument when defining the
	 * service.
	 */
	public void init() {
		// init some harbours
		ArrayList<Harbour> harbours = new ArrayList<Harbour>();
		
		// Romania
		harbours.add(new Harbour("Calarasi", 44.22f, 27.33f));
		harbours.add(new Harbour("Giurgiu", 43.92f, 25.98f));
		harbours.add(new Harbour("Calafat", 44.0f, 22.93f));
		harbours.add(new Harbour("Orsova", 44.74f, 22.20f));
		
		harbours.add(new Harbour("Sulina", 45.17f, 29.67f));
		harbours.add(new Harbour("Tulcea", 45.17f, 28.82f));
		harbours.add(new Harbour("Galati", 45.42f, 28.08f));
		// Serbia
		harbours.add(new Harbour("Belgrade", 44.825556f, 20.4775f));
		// Croatia
		harbours.add(new Harbour("Vukovar", 45.359167f, 18.989167f));
		// Ungaria
		harbours.add(new Harbour("Csepel", 47.443611f, 19.061389f));
		// Slovacia
		harbours.add(new Harbour("Bratislava", 48.130556f, 17.145f));
		// Austria
		harbours.add(new Harbour("Vienna", 48.21f, 16.37f));
		harbours.add(new Harbour("Krems", 48.403611f, 15.645f));
		harbours.add(new Harbour("Enns", 48.235f, 14.511667f));
		harbours.add(new Harbour("Linz", 48.3044f, 14.3261f));
		// Germania
		harbours.add(new Harbour("Kelheim", 48.910278f ,11.919444f));
		
		harbours.add(new Harbour("Bayernhafen Regensburg", 49.03f, 12.10f));
		harbours.add(new Harbour("Deggendorf", 48.84f, 12.96f));
					
		// Belgia
		harbours.add(new Harbour("Antwerp", 51.22f, 4.40f));
		harbours.add(new Harbour("Ghent", 51.07f, 3.73f));
		harbours.add(new Harbour("Bruges", 51.23f, 3.22f));
		
		for (int i = 0; i < harbours.size(); i++) {
			harboursDAO.create(harbours.get(i));
		}
		
		// add some employees
		ArrayList<Employee> employees = new ArrayList<Employee>();
		Calendar.getInstance().add(Calendar.YEAR, -3);
		Date threeYAgo = Calendar.getInstance().getTime();
		
		employees.add(new Employee("Gigi", "Papalapte", "0723990118", 
				"Some address here", threeYAgo, "Ofiter 3", 
				"Officer 3", 3000));

		employees.add(new Employee("Johan", "Kenens", "0321378001", 
				"Other address here", threeYAgo, "Capitan", 
				"Capitan", 6000));
		
		employees.add(new Employee("Ion", "Mazare", "03213780990", 
				"Other address here", threeYAgo, "Capitan", 
				"Officer 3", 6000));
		
		employees.add(new Employee("Mihai", "Deleanu", "0321378001", 
				"Other address here", threeYAgo, "Capitan", 
				"Capitan", 6000));
		
		employees.add(new Employee("Laur", "Zarzare", "0321378001", 
				"Other address here", threeYAgo, "Capitan", 
				"Capitan", 6000));
		
		for (int i = 0; i < employees.size(); i++) {
			employeesDAO.create(employees.get(i));
		}
		
		// init some ships
		ArrayList<Ship> ships = new ArrayList<Ship>();
		ships.add(new CruiseShip("MS Amadolce", 160, 145, 110, 25,  30, "gasoline", harbours.get(4), harbours.get(5), harbours.get(0), Calendar.getInstance().getTime(), "habar nu am", 50, 70));
		ships.add(new CruiseShip("MS Amadeus", 160, 145, 110, 25, 30, "gasoline", harbours.get(7), harbours.get(7), harbours.get(10),  Calendar.getInstance().getTime(), "no ideea", 30, 80));
		ships.add(new Cargo("Victoria", 1500, 1400, 130, 30,  30, "diesel", harbours.get(6), harbours.get(7),  harbours.get(7), Calendar.getInstance().getTime(), "cereals", 3));
		ships.add(new Cargo("Sea Cloud I", 2000, 1800, 150, 30,  30, "diesel", harbours.get(7), harbours.get(7), harbours.get(11), Calendar.getInstance().getTime(), "fruits and vegetables", 2));
		ships.add(new Tanker("Santa Maria", 1000, 800, 110, 25, 30, "gasoline", harbours.get(11), harbours.get(11), harbours.get(14),  Calendar.getInstance().getTime(), "gasoline"));
		
//		employees.get(0).setShip(ships.get(0));
//		employees.get(1).setShip(ships.get(0));
		
		Set<Employee> crew= new HashSet<Employee>();
		crew.add(employees.get(0));
		crew.add(employees.get(1));
		ships.get(0).setCrew(crew);
		
		for (int i = 0; i < ships.size(); i++) {
			shipsDAO.create(ships.get(i));
		}
		
		// init some routes
		ArrayList<Route> routes = new ArrayList<Route>();
		ArrayList<Harbour> routeHarbours = new ArrayList<Harbour>();
		Date today = Calendar.getInstance().getTime();
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, 7);
		Date after7Days = calendar.getTime();
		
		routeHarbours.add(harbours.get(0));
		routeHarbours.add(harbours.get(1));
		routeHarbours.add(harbours.get(2));
		routeHarbours.add(harbours.get(3));
		routeHarbours.add(harbours.get(7));
		routeHarbours.add(harbours.get(8));
		routeHarbours.add(harbours.get(9));
		routeHarbours.add(harbours.get(10));
		// Calarasi -> Viena
		routes.add(new Route(today, null, after7Days, 100, ships.get(0), routeHarbours));
		
		routeHarbours = new ArrayList<Harbour>();
		routeHarbours.add(harbours.get(10));
		routeHarbours.add(harbours.get(9));
		routeHarbours.add(harbours.get(8));
		routeHarbours.add(harbours.get(7));
		routes.add(new Route(today, null, after7Days, 100, ships.get(1), routeHarbours));
			
		for (int i = 0; i < routes.size(); i++) {
			routesDAO.create(routes.get(i));
		}
		
		//create test users
		List<User> users = new ArrayList<User>();
		String userIds[] = new String[] { "luiza", "Luiza Udroiu", "ROLE_USER",
				"georgiana", "Georgiana Udrescu", "ROLE_USER", "admin",
				"Administrator", "ROLE_USER,ROLE_ADMIN" };

		for (int i = 0; i < userIds.length; i += 3) {
			User user = new User();
			user.setUserId(userIds[i]);
			user.setUserName(userIds[i + 1]);
			user.setUserPass("nautilus"); // btw this should be encrypted
			
			users.add(user);
			create(user);
			
			// For each user, tokenize and give the corresponding roles
			StringTokenizer st = new StringTokenizer(userIds[i + 2], ",");
			while (st.hasMoreTokens()) {
				UserRole role = new UserRole();
				role.setUserId(userIds[i]);
				role.setAuthority(st.nextToken().trim());

				createRole(role);
			}
		}
	}

	@Required
	public void setUsersDAO(GenericDAO<User, Long> usersDao) {
		this.usersDAO = usersDao;
	}

	@Required
	public void setUsersRolesDAO(GenericDAO<UserRole, Long> usersRolesDao) {
		this.usersRolesDAO = usersRolesDao;
	}

	@Required
	public void setHarboursDAO(GenericDAO<Harbour, Long> harboursDAO) {
		this.harboursDAO = harboursDAO;
	}
	
	@Required
	public void setShipsDAO(GenericDAO<Ship, Long> shipsDAO) {
		this.shipsDAO = shipsDAO;
	}

	@Required
	public void setRoutesDAO(GenericDAO<Route, Long> routesDAO) {
		this.routesDAO = routesDAO;
	}

	@Required
	public void setEmployeesDAO(GenericDAO<Employee, Long> employeesDAO) {
		this.employeesDAO = employeesDAO;
	}	
}
